package com.jl;

import lombok.SneakyThrows;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.StringJoiner;

public class DockerFileUtils {

    /**
     * 添加镜像
     *
     * @param image
     * @return
     */
    public Maintainer image(String image) {
        StringJoiner dockerFile = new StringJoiner("\n");
        dockerFile.add(String.format("FROM %s", image));
        return new Maintainer(dockerFile);
    }

    public class Maintainer {

        private StringJoiner dockerFile;

        public Maintainer(StringJoiner dockerFile) {
            this.dockerFile = dockerFile;
        }

        /**
         * 添加作者
         *
         * @param maintainer
         */
        public AddAndExpose maintainer(String maintainer) {
            dockerFile.add(String.format("MAINTAINER %s", maintainer));
            return new AddAndExpose(dockerFile);
        }
    }


    public class AddAndExpose {
        private StringJoiner dockerFile;

        public AddAndExpose(StringJoiner dockerFile) {
            this.dockerFile = dockerFile;
        }

        /**
         * 添加端口
         *
         * @param ports
         * @return
         */
        public AddAndRunAndEnv port(int... ports) {
            if (ports.length > 0) {
                StringJoiner joiner = new StringJoiner(" ");
                for (int port : ports) {
                    joiner.add(String.valueOf(port));
                }
                dockerFile.add(String.format("EXPOSE %s", joiner.toString()));
            }
            return new AddAndRunAndEnv(dockerFile);
        }

        /**
         * 添加文件
         *
         * @param sourcePath
         * @param targetPath
         */
        public AddAndRunAndEnv add(String sourcePath, String targetPath) {
            dockerFile.add(String.format("ADD %s %s", sourcePath, targetPath));
            return new AddAndRunAndEnv(dockerFile);
        }
    }

    public class AddAndRunAndEnv {
        private StringJoiner dockerFile;

        public AddAndRunAndEnv(StringJoiner dockerFile) {
            this.dockerFile = dockerFile;
        }

        /**
         * 添加环境变量
         *
         * @param key
         * @param value
         * @return
         */
        public AddAndRunAndEnv env(String key, String value) {
            dockerFile.add(String.format("ENV %s %s", key, value));
            return this;
        }

        /**
         * 添加文件
         *
         * @param sourcePath
         * @param targetPath
         */
        public AddAndRunAndEnv add(String sourcePath, String targetPath) {
            dockerFile.add(String.format("ADD %s %s", sourcePath, targetPath));
            return this;
        }

        /**
         * 添加命令
         *
         * @param commands
         */
        public AddAndRunAndEnv run(String... commands) {
            if (commands.length == 0) {
                return this;
            }
            if (commands.length > 1) {
                StringJoiner joiner = new StringJoiner(" && ");
                for (String command : commands) {
                    joiner.add(command);
                }
                dockerFile.add(String.format("RUN %s", String.format("/bin/sh -c '%s'", joiner.toString())));
            } else {
                dockerFile.add(String.format("RUN %s", commands[0]));
            }
            return this;
        }

        /**
         * 设置工作目录
         *
         * @param workdir
         */
        public AddAndRunAndEnv workdir(String workdir) {
            dockerFile.add(String.format("WORKDIR %s", workdir));
            return this;
        }

        /**
         * 添加启动容器时执行的命令
         *
         * @param commands
         * @return
         */
        @SneakyThrows
        public Save cmd(String... commands) {
            StringJoiner joiner = new StringJoiner(" | ");
            for (String command : commands) {
                joiner.add(command);
            }
            dockerFile.add(String.format("CMD [\"sh\",\"-c\",\"%s\"]", joiner.toString()));
            return new Save(dockerFile);
        }
    }

    public class Save {

        private StringJoiner dockerFile;

        public Save(StringJoiner dockerFile) {
            this.dockerFile = dockerFile;
        }

        @SneakyThrows
        public void save(String path) {
            OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(path));
            try {
                outputStream.write(dockerFile.toString().getBytes());
                outputStream.flush();
                System.out.println("文件生成完毕：\n\n" + dockerFile.toString());
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    outputStream.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
